package com.lagou.handler;

import com.lagou.service.RpcRequest;
import com.lagou.service.UserService;
import com.lagou.service.com.lagou.zookeeper.ZooKeeperServiceRegistry;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.concurrent.ThreadLocalRandom;

import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;


@Component
public class RpcServerHandler extends SimpleChannelInboundHandler<RpcRequest> implements ApplicationContextAware {

    private static ApplicationContext applicationContext2;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        RpcServerHandler.applicationContext2 = applicationContext;
    }

    @Override
    public void channelRead0(final ChannelHandlerContext ctx, RpcRequest request) throws Exception {

        long time = System.currentTimeMillis();
        Object handle = handle(request);
        // 写入 RPC 响应对象并自动关闭连接
        ctx.writeAndFlush("success").addListener(ChannelFutureListener.CLOSE);
        Thread.sleep(ThreadLocalRandom.current().nextInt(4000));
        long endTime = System.currentTimeMillis() - time;
        System.out.println("time: " + endTime);

        ZooKeeperServiceRegistry zooKeeperServiceRegistry = new ZooKeeperServiceRegistry("127.0.0.1");
        zooKeeperServiceRegistry.addServiceResponseInfo(UserService.class.getName(), "127.0.0.1:8992",endTime,System.currentTimeMillis());
    }

    private Object handle(RpcRequest request) throws Exception {

        // 获取服务对象
        Class<?> clazz = Class.forName(request.getClassName());
        Object serviceBean = applicationContext2.getBean(clazz);

        // 获取反射调用所需的参数
        Class<?> serviceClass = serviceBean.getClass();
        String methodName = request.getMethodName();
        Class<?>[] parameterTypes = request.getParameterTypes();
        Object[] parameters = request.getParameters();
        // 执行反射调用
        Method method = serviceClass.getMethod(methodName, parameterTypes);
        method.setAccessible(true);
        return method.invoke(serviceBean, parameters);

    }
}